﻿/* Copyright (c) 2009 Jakub Müller
 * 
 * Permission is hereby granted, free of charge,
 * to any person obtaining a copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software,
 * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * 
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace KompoziceMistoDedicnosti {
	/// <summary>
	/// Bázová třída pro UserControly v tomto projektu, které obsahují MenuStrip a ToolStrip.
	/// </summary>
	public partial class StripedUserControl : UserControl, IMenuStripItemsProvider, IToolStripItemsProvider {
		private IList<IMenuStripItemsProvider> menuStripItemsProviders;
		/// <summary>
		/// Kolekce dodatečných poskytovatelů položek pro MenuStrip.
		/// </summary>
		[Browsable( false )]
		[DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )]
		public IList<IMenuStripItemsProvider> MenuStripItemsProviders {
			get { return this.menuStripItemsProviders; }
			private set { this.menuStripItemsProviders = value; }
		}

		private IList<IToolStripItemsProvider> toolStripItemsProviders;
		/// <summary>
		/// Kolekce dodatečných poskytovatelů položek pro ToolStrip.
		/// </summary>
		[Browsable( false )]
		[DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )]
		public IList<IToolStripItemsProvider> ToolStripItemsProviders {
			get { return this.toolStripItemsProviders; }
			private set { this.toolStripItemsProviders = value; }
		}

		public StripedUserControl() {
			InitializeComponent();

			this.MenuStripItemsProviders = new List<IMenuStripItemsProvider>();
			this.ToolStripItemsProviders = new List<IToolStripItemsProvider>();

			this.Load += new EventHandler( StripedUserControl_Load );
		}

		protected virtual void StripedUserControl_Load( object sender, EventArgs e ) {
			if ( this.IsInRuntimeMode() ) {
				this.ReloadMenuStrips();
				this.ReloadToolStrips();
			}
		}

		/// <summary>
		/// Znovu načte položky pro MenuStrip.
		/// </summary>
		public virtual void ReloadMenuStrips() {
			this.mainMenuStrip.SuspendLayout();
			try {
				var mainMenuItems = this.mainMenuStrip.Items;

				mainMenuItems.Clear();

				var menuStripItems = this.GetMenuStripItems();
				if ( null != menuStripItems ) {
					foreach ( var menuStripItem in menuStripItems.OrderBy( t => t.MergeIndex ) ) {
						if ( null == menuStripItem ) { continue; }

						var ownerItem = menuStripItem.OwnerItem;
						if ( null != ownerItem ) {
							var dropDownItem = ownerItem as ToolStripDropDownItem;
							if ( null != dropDownItem ) {
								dropDownItem.DropDownItems.Remove( menuStripItem );
							}
						}

						mainMenuItems.Add( menuStripItem );
					}
				}
			}
			finally {
				this.mainMenuStrip.ResumeLayout( true );
			}

			var firstVisibleItem = this.mainMenuStrip.Items.OfType<ToolStripItem>().Where( t => t.Visible ).FirstOrDefault();
			this.mainMenuStrip.Visible = (null != firstVisibleItem);
		}

		/// <summary>
		/// Znovu načte položky pro ToolStrip.
		/// </summary>
		public virtual void ReloadToolStrips() {
			this.mainToolStrip.SuspendLayout();
			try {
				var mainToolItems = this.mainToolStrip.Items;

				mainToolItems.Clear();

				var toolStripItems = this.GetToolStripItems();
				if ( null != toolStripItems ) {
					foreach ( var toolStripItem in toolStripItems.OrderBy( t => t.MergeIndex ) ) {
						if ( null == toolStripItem ) { continue; }

						var ownerItem = toolStripItem.OwnerItem;
						if ( null != ownerItem ) {
							var dropDownItem = ownerItem as ToolStripDropDownItem;
							if ( null != dropDownItem ) {
								dropDownItem.DropDownItems.Remove( toolStripItem );
							}
						}

						mainToolItems.Add( toolStripItem );
					}
				}
			}
			finally {
				this.mainToolStrip.ResumeLayout( true );
			}

			var firstVisibleItem = this.mainToolStrip.Items.OfType<ToolStripItem>().Where( t => t.Visible ).FirstOrDefault();
			this.mainToolStrip.Visible = (null != firstVisibleItem);
		}

		/// <summary>
		/// Vrací VLASTNÍ položky, které se mají zobrazit v MenuStripu.
		/// Pokud není metoda přepsána (override), vrací prázdné pole.
		/// </summary>
		/// <returns></returns>
		protected virtual IEnumerable<ToolStripItem> GetOwnMenuStripItems() {
			return new ToolStripItem[0];
		}

		/// <summary>
		/// Vrací položky, které se mají zobrazit v ToolStripu.
		/// Pokud není metoda přepsána (override), vrací prázdné pole.
		/// </summary>
		/// <returns></returns>
		public virtual IEnumerable<ToolStripItem> GetOwnToolStripItems() {
			return new ToolStripItem[0];
		}

		#region IMenuStripItemsProvider Members
		/// <summary>
		/// Vrací sloučené položky, které se mají zobrazit v MenuStripu.
		/// </summary>
		/// <returns></returns>
		public virtual IEnumerable<ToolStripItem> GetMenuStripItems() {
			IEnumerable<ToolStripItem> ret;
			var ownMenuStripItems = this.GetOwnMenuStripItems();
			if ( null != ownMenuStripItems ) {
				ret = ownMenuStripItems;
			}
			else {
				ret = new ToolStripItem[0];
			}

			foreach ( var menuItemsProvider in this.MenuStripItemsProviders ) {
				if ( null == menuItemsProvider ) { continue; }
				var additionalMenuStripItems = menuItemsProvider.GetMenuStripItems();
				if ( null != additionalMenuStripItems ) {
					ret = ret.Concat( additionalMenuStripItems );
				}
			}

			return ret;
		}

		#endregion

		#region IToolStripItemsProvider Members
		/// <summary>
		/// Vrací sloučené položky, které se mají zobrazit v ToolStripu.
		/// </summary>
		/// <returns></returns>
		public virtual IEnumerable<ToolStripItem> GetToolStripItems() {
			IEnumerable<ToolStripItem> ret;
			var ownMenuStripItems = this.GetOwnToolStripItems();
			if ( null != ownMenuStripItems ) {
				ret = ownMenuStripItems;
			}
			else {
				ret = new ToolStripItem[0];
			}

			foreach ( var menuItemsProvider in this.ToolStripItemsProviders ) {
				if ( null == menuItemsProvider ) { continue; }
				var additionalMenuStripItems = menuItemsProvider.GetToolStripItems();
				if ( null != additionalMenuStripItems ) {
					ret = ret.Concat( additionalMenuStripItems );
				}
			}

			return ret;
		}

		#endregion
	}
}
